using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Xml.Serialization;
using System.Collections;
using TheLogWatcher.Properties;

namespace TheLogWatcher
{
    public class FormatSettings
    {
        public FormatSettings()
        {
        }

        public FormatSettings(bool standard)
        {
            this.Name = "Nameless Log Format";
            this.Index = -1;
            //
            if (standard)
            {
                // Create an instance with standard content
                addObj("Day", 2, "");
                addObj("Month", 2, ".");
                addObj("Year", 2, ".");
                addObj("Hour", 2, "  ");
                addObj("Minute", 2, ":");
                addObj("Second", 2, ":");
                addObj("Type", 1, " [");
                addObj("Text", 0, "]");
            }
        }

        #region FIELDS

        /// <summary>
        ///     The actual index if this format type.
        /// </summary>
        [XmlIgnore()]
        private int index = -1;
        public int Index
        {
            set { this.index = value; }
            get { return this.index; }
        }

        /// <summary>
        ///     The name of this log format.
        /// </summary>
        [XmlElementAttribute("Name")]
        public string Name
        {
            set { this.name = value; }
            get { return this.name; }
        }
        private string name;

        /// <summary>
        ///     List of all format settings contained is this format definition.
        /// </summary>
        [XmlArray("FormatTypes"), XmlArrayItem("FormatType", typeof(FormatSettingsType))]
        public ArrayList FormatTypes
        {
            set { this.formatTypes = value; }
            get { return this.formatTypes; }
        }
        private ArrayList formatTypes;

        #endregion

        #region METHODS

        public string compileRegEx()
        {
            //FormatConfigs formatConfigs = StaticXmlStorage.getLogFormatBaseDefs();
            FormatConfigs formatConfigs = PredefinedConfigs.Configs[0];
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < this.formatTypes.Count; i++)
            {
                FormatSettingsType type = (FormatSettingsType)this.formatTypes[i];
                // Append previous text
                // builder.Append(escapeSpecialRegExChars(type.Text));
                builder.Append(type.Text);

                foreach (FormatConfigsType configType in formatConfigs.FormatTypes)
                {
                    if (configType.Name.Equals(type.Name))
                    {
                        foreach (FormatConfigsTypeProperty property in configType.Properties)
                        {
                            if (property.ID != 0 && property.ID == type.PropertyID)
                            {
                                // Append regex group
                                builder.Append("(?<" + type.Name + ">" + property.RegEx + ")");
                                break;
                            }
                        }
                        break;
                    }
                    
                }
            }
            getListName();
            return builder.ToString();
        }

        /// <summary>
        ///     Builds a list name that contains:
        ///     <para>1. The name that was defined</para>
        ///     <para>2. a "#" + number if several entries share the same name</para>
        ///     <para>3. the full date time expression in brackets</para>
        /// </summary>
        /// <returns></returns>
        public string getListName()
        {
            StringBuilder builder = new StringBuilder(this.Name + ":  ");
            //FormatConfigs formatConfigs = StaticXmlStorage.getLogFormatBaseDefs();
            FormatConfigs formatConfigs = PredefinedConfigs.Configs[0];

            for (int i = 0; i < this.formatTypes.Count; i++)
            {
                FormatSettingsType type = (FormatSettingsType)this.formatTypes[i];
                // Append previous text
                builder.Append(type.Text);

                foreach (FormatConfigsType configType in formatConfigs.FormatTypes)
                {
                    if (configType.Name.Equals(type.Name))
                    {
                        foreach (FormatConfigsTypeProperty property in configType.Properties)
                        {
                            if (property.ID != 0 && property.ID == type.PropertyID)
                            {
                                // Append date time expression
                                builder.Append(property.DateFormat);
                                break;
                            }
                        }
                    }
                }
            }
            return builder.ToString();
        }

        public string generateExample()
        {
            // Set standard example date
            DateTime dt = new DateTime(2007, 12, 31, 12, 22, 58);
            //FormatConfigs formatConfigs = StaticXmlStorage.getLogFormatBaseDefs();
            FormatConfigs formatConfigs = PredefinedConfigs.Configs[0];
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < this.formatTypes.Count; i++)
            {
                FormatSettingsType type = (FormatSettingsType)this.formatTypes[i];
                // Append previous text
                builder.Append(type.Text);

                foreach (FormatConfigsType configType in formatConfigs.FormatTypes)
                {
                    if (configType.Name.Equals(type.Name))
                    {
                        foreach (FormatConfigsTypeProperty property in configType.Properties)
                        {
                            if (property.ID != 0 && property.ID == type.PropertyID)
                            {
                                if (type.Name.Equals("Type"))
                                {
                                    // Append type as text
                                    builder.Append("ERROR");
                                }
                                else if (type.Name.Equals("Package"))
                                {
                                    // Append package as text
                                    builder.Append("org.handler.*");
                                }
                                else
                                {
                                    // Append date time expression
                                    string formattedPart = dt.ToString(property.DateFormat);
                                    builder.Append(formattedPart);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            return builder.ToString();
        }

        /// <summary>
        ///     Escapes all characters that could influence the regular expression.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private string escapeSpecialRegExChars(string input)
        {
            string output = input.Replace(@"\", @"\\");
            output = output.Replace("[", @"\[");
            output = output.Replace("]", @"\]");
            output = output.Replace("(", @"\(");
            output = output.Replace(")", @"\)");
            output = output.Replace(".", @"\.");
            output = output.Replace("$", @"\$");
            output = output.Replace("^", @"\^");
            output = output.Replace("*", @"\*");
            output = output.Replace("+", @"\+");
            output = output.Replace("|", @"\|");
            output = output.Replace("?", @"\?");
            return output;
        }

        public void addObj(string uid, int propertyId, string text)
        {
            int x = 5;
            if (this.formatTypes != null)
            {
                x += this.formatTypes.Count * 95;
            }
            int y = 1;
            addObj(uid, x, y, propertyId, text);
        }

        private void addObj(string uid, int x, int y, int propertyId, string text)
        {
            FormatSettingsType type = new FormatSettingsType(uid, x, y, text);
            if (this.formatTypes == null)
            {
                this.formatTypes = new ArrayList();
            }
            type.PropertyID = propertyId;
            this.formatTypes.Add(type);
        }

        #endregion
    }
}

